/*
   PureMVC - Copyright(c) 2006-08 Futurescale, Inc., Some rights reserved.
   Your reuse is governed by the Creative Commons Attribution 3.0 United States License
 */
package org.puremvc.as3.core {

import org.puremvc.as3.interfaces.*;


/**
 * A Singleton <code>IModel</code> implementation.
 *
 * <P>
 * In PureMVC, the <code>Model</code> class provides
 * access to model objects (Proxies) by named lookup.
 *
 * <P>
 * The <code>Model</code> assumes these responsibilities:</P>
 *
 * <UL>
 * <LI>Maintain a cache of <code>IProxy</code> instances.</LI>
 * <LI>Provide methods for registering, retrieving, and removing
 * <code>IProxy</code> instances.</LI>
 * </UL>
 *
 * <P>
 * Your application must register <code>IProxy</code> instances
 * with the <code>Model</code>. Typically, you use an
 * <code>ICommand</code> to create and register <code>IProxy</code>
 * instances once the <code>Facade</code> has initialized the Core
 * actors.</p>
 *
 * @see org.puremvc.as3.patterns.proxy.Proxy Proxy
 * @see org.puremvc.as3.interfaces.IProxy IProxy
 */
public class Model implements IModel {

	// Mapping of proxyNames to IProxy instances
	protected var proxyMap:Array;

	// Singleton instance
	protected static var instance:IModel;

	// Message Constants
	protected const SINGLETON_MSG:String = "Model Singleton already constructed!";

	/**
	 * Constructor.
	 *
	 * <P>
	 * This <code>IModel</code> implementation is a Singleton,
	 * so you should not call the constructor
	 * directly, but instead call the static Singleton
	 * Factory method <code>Model.getInstance()</code>
	 *
	 * @throws Error Error if Singleton instance has already been constructed
	 *
	 */
	public function Model(){
		if (instance != null)
			throw Error(SINGLETON_MSG);
		instance = this;
		proxyMap = new Array();
		initializeModel();
	}

	/**
	 * Initialize the Singleton <code>Model</code> instance.
	 *
	 * <P>
	 * Called automatically by the constructor, this
	 * is your opportunity to initialize the Singleton
	 * instance in your subclass without overriding the
	 * constructor.</P>
	 *
	 * @return void
	 */
	protected function initializeModel():void {
	}

	/**
	 * <code>Model</code> Singleton Factory method.
	 *
	 * @return the Singleton instance
	 */
	public static function getInstance():IModel {
		if (instance == null)
			instance = new Model();
		return instance;
	}

	/**
	 * Register an <code>IProxy</code> with the <code>Model</code>.
	 *
	 * @param proxy an <code>IProxy</code> to be held by the <code>Model</code>.
	 */
	public function registerProxy(proxy:IProxy):void {
		proxyMap[proxy.getProxyName()] = proxy;
		proxy.onRegister();
	}

	/**
	 * Retrieve an <code>IProxy</code> from the <code>Model</code>.
	 *
	 * @param proxyName
	 * @return the <code>IProxy</code> instance previously registered with the given <code>proxyName</code>.
	 */
	public function retrieveProxy(proxyName:String):IProxy {
		return proxyMap[proxyName];
	}

	/**
	 * Check if a Proxy is registered
	 *
	 * @param proxyName
	 * @return whether a Proxy is currently registered with the given <code>proxyName</code>.
	 */
	public function hasProxy(proxyName:String):Boolean {
		return proxyMap[proxyName] != null;
	}

	/**
	 * Remove an <code>IProxy</code> from the <code>Model</code>.
	 *
	 * @param proxyName name of the <code>IProxy</code> instance to be removed.
	 * @return the <code>IProxy</code> that was removed from the <code>Model</code>
	 */
	public function removeProxy(proxyName:String):IProxy {
		var proxy:IProxy = proxyMap[proxyName] as IProxy;
		if (proxy){
			proxyMap[proxyName] = null;
			proxy.onRemove();
		}
		return proxy;
	}


}
}